using MediatR;
using Microsoft.EntityFrameworkCore;
using SupplierCustomerManagement.Infrastructure;
using SupplierCustomerManagement.Read.API.Applications.Commands.lambing;
using SupplierCustomerManagement.Read.API.Dtos.Lambing;

namespace SupplierCustomerManagement.Read.API.Applications.CommandHandlters.lambing
{
    public class GetLactationMonthlyStatsQueryHandler : IRequestHandler<GetLactationMonthlyStatsQuery, List<LactationMonthlyStatsDto>>
    {
        private readonly SupplierDbContext _db;
        private readonly ILogger<GetLactationMonthlyStatsQueryHandler> _logger;

        public GetLactationMonthlyStatsQueryHandler(SupplierDbContext db, ILogger<GetLactationMonthlyStatsQueryHandler> logger)
        {
            _db = db;
            _logger = logger;
        }

        public async Task<List<LactationMonthlyStatsDto>> Handle(GetLactationMonthlyStatsQuery request, CancellationToken cancellationToken)
        {
            if (!int.TryParse(request.year, out var year))
            {
                year = DateTime.UtcNow.Year;
            }

            var query = _db.LambingRecords.AsNoTracking().Where(r => r.LambingDate.Year == year);
            if (request.farmId.HasValue)
            {
                var fid = request.farmId.Value;
                query = query.Where(r => r.FarmId == fid);
            }

            var grouped = await query
                .GroupBy(r => r.LambingDate.Month)
                .Select(g => new
                {
                    month = g.Key,
                    litterCount = g.Count(),
                    lambCount = g.Sum(x => (int?)x.TotalLambs) ?? 0,
                    avgHealthy = g.Average(x => (double)(x.HealthyLambs ?? 0)),
                    avgWeak = g.Average(x => (double)(x.WeakLambs ?? 0)),
                    avgDeformed = g.Average(x => (double)(x.DeformedLambs ?? 0)),
                    avgStillbirth = g.Average(x => (double)(x.DeadLambs)),
                    avgMummy = g.Average(x => (double)(x.MummifiedFetuses ?? 0)),
                    avgAbnormal = g.Average(x => (double)(x.AbnormalFetuses ?? 0))
                })
                .ToListAsync(cancellationToken);

            var dict = grouped.ToDictionary(
                k => k.month,
                v => new LactationMonthlyStatsDto
                {
                    month = v.month,
                    litterCount = v.litterCount,
                    lambCount = v.lambCount,
                    avgHealthy = Math.Round((decimal)v.avgHealthy, 3),
                    avgWeak = Math.Round((decimal)v.avgWeak, 3),
                    avgDeformed = Math.Round((decimal)v.avgDeformed, 3),
                    avgStillbirth = Math.Round((decimal)v.avgStillbirth, 3),
                    avgMummy = Math.Round((decimal)v.avgMummy, 3),
                    avgAbnormal = Math.Round((decimal)v.avgAbnormal, 3)
                });

            var result = new List<LactationMonthlyStatsDto>();
            for (int m = 1; m <= 12; m++)
            {
                if (dict.TryGetValue(m, out var dto))
                {
                    result.Add(dto);
                }
                else
                {
                    result.Add(new LactationMonthlyStatsDto
                    {
                        month = m,
                        litterCount = 0,
                        lambCount = 0,
                        avgHealthy = 0,
                        avgWeak = 0,
                        avgDeformed = 0,
                        avgStillbirth = 0,
                        avgMummy = 0,
                        avgAbnormal = 0
                    });
                }
            }

            return result;
        }
    }
}
